package com.jiang.annotation.valid.custom;

import org.apache.commons.lang3.StringUtils;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.Arrays;
import java.util.Objects;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * @author jiangzhe
 *
 * @apiNote
 * 自定义限定参数注解，限定参数只能取某几个值中的一个的校验注解， String[]/int[] 数组中的某元素（支持能否为空）<br>
 * message 可以不写，默认汇集数组所有元素的值并提示 "必须为指定值：[xx,xx,...]"<br>
 *<br>
 * {@code
 * @InValuesCheck(intValues = {20, 21, 22, 23, 24}, canNull = false, message = "value must be in {intValues}")
 * private int graduateAge;
 * }
 */
@Target({FIELD, PARAMETER})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {InValuesCheck.InValuesValidator.class})
public @interface InValuesCheck {

    String message() default "";

    String[] strValues() default {};

    int[] intValues() default {};

    // 是否可以为空，默认为空，为空值则检查通过
    boolean canNull() default true;

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    // 指定多个时使用
    @Target({FIELD, PARAMETER})
    @Retention(RUNTIME)
    @Documented
    @interface List {
        InValuesCheck[] value();
    }

    class InValuesValidator implements ConstraintValidator<InValuesCheck, Object> {
        private String[] strValues;
        private int[] intValues;
        private boolean canNull;
        private String message;

        @Override
        public void initialize(InValuesCheck constraintAnnotation) {
            strValues = constraintAnnotation.strValues();
            intValues = constraintAnnotation.intValues();
            canNull = constraintAnnotation.canNull();
            message = constraintAnnotation.message();
        }

        @Override
        public boolean isValid(Object value, ConstraintValidatorContext context) {
            if (Objects.nonNull(value)) {
                String defaultMsg = null;
                if (value instanceof String) {
                    for (String s : strValues) {
                        if (s.equals(value)) {
                            return true;
                        }
                    }
                    defaultMsg = Arrays.asList(strValues).toString();
                } else if (value instanceof Integer) {
                    for (int s : intValues) {
                        if (s == ((Integer) value).intValue()) {
                            return true;
                        }
                    }
                    defaultMsg = Arrays.asList(intValues).toString();
                }
                if(StringUtils.isEmpty(message)){
                    context.disableDefaultConstraintViolation();
                    context.buildConstraintViolationWithTemplate("必须为指定值：" + defaultMsg).addConstraintViolation();
                }
                return false;
            }
            return canNull;
        }
    }
}
